﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using celinda.Class;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Criterion;

namespace celinda.Repository
{
    public class BaseRepository<T> : IRepository<T>
    {
        static ISessionFactory _sessionFactory = null;
        public static ISessionFactory CreateSessionFactory()
        {

            _sessionFactory = FluentNHibernate.Cfg.Fluently.Configure()
                                .Database(SQLiteConfiguration.Standard.ShowSql().ConnectionString("Data Source=" + Class.Outils.repBase + Class.Outils.ficBase))
                                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Societe>())
                                .BuildSessionFactory();

            return _sessionFactory;

        }

        public static void CreateBase()
        {
            FluentNHibernate.Cfg.Fluently.Configure()
                                .Database(SQLiteConfiguration.Standard.ConnectionString("Data Source=" + Class.Outils.repBase + Class.Outils.ficBase))
                                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Societe>())
                                .ExposeConfiguration(CreateSchema)
                                .BuildSessionFactory();
        }

        /// <summary>
        /// Cela ne fait qu'ajouter des colonnes ou tables manquantes
        /// Cela ne supprime jamais des colonnes ou tables
        /// </summary>
        public static void UpdateBase()
        {
            FluentNHibernate.Cfg.Fluently.Configure()
                                .Database(SQLiteConfiguration.Standard.ConnectionString("Data Source=" + Class.Outils.repBase + Class.Outils.ficBase))
                                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Societe>())
                                .ExposeConfiguration(UpdateSchema)
                                .BuildSessionFactory();
        }

        private static void CreateSchema(Configuration config)
        {
            new SchemaExport(config).Create(true, true);
        }

        private static void UpdateSchema(Configuration config)
        {
            new SchemaUpdate(config).Execute(true, true);
        }

        public static ISession GetNHBSession()
        {
            if (_sessionFactory == null)
            {
                _sessionFactory = CreateSessionFactory();

            }
            return _sessionFactory.OpenSession();
        }


        public IList<T> GetAll()
        {
            IList<T> list;
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                list = session.CreateCriteria(typeof(T)).List<T>();
                session.Transaction.Commit();

            }

            return list;

        }
        
        public IList<T> GetAllActif()
        {
            IList<T> list;
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                list = session.CreateCriteria(typeof(T))
                    .Add(Restrictions.Eq("Etat", Const.EtatActif))
                    .List<T>();
                session.Transaction.Commit();

            }

            return list;

        }

        public T GetByID(int id)
        {
            T list;
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                list = session.Get<T>(id);
                session.Transaction.Commit();

            }

            return list;


        }
        public void Save(T obj)
        {
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                ((IBaseClasse)obj).DateCreation = DateTime.Now;
                ((IBaseClasse)obj).DateModification = DateTime.Now;
                ((IBaseClasse)obj).Etat = Class.Const.EtatActif;
                session.Save(obj);
                session.Transaction.Commit();

            }

        }
        public void Delete(T obj)
        {
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                session.Delete(obj);
                session.Transaction.Commit();

            }
        }
        public void Update(T obj)
        {
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                session.Update(obj);
                ((IBaseClasse)obj).DateModification = DateTime.Now;
                session.Transaction.Commit();
            }

        }

        public void DeleteByID(string idPropertyName, int objId)
        {
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                var result = session.CreateCriteria(typeof(T))
                                     .Add(Restrictions.Eq(idPropertyName, objId))
                                     .List<T>();
                if (result.Count > 0)
                {
                    session.Delete(result[0]);
                }
                session.Transaction.Commit();
            }

        }

        public IList<T> GetByPropertyName(string idPropertyName, string pvalue)
        {


            IList<T> list;
            // implimentation here 
            using (ISession session = GetNHBSession())
            {
                session.BeginTransaction();
                list = session.CreateCriteria(typeof(T))
                                      .Add(Restrictions.Like(idPropertyName, pvalue, MatchMode.Anywhere))
                                      .List<T>();

                session.Transaction.Commit();
            }
            return list;

        }
    }
}
